/**
 *  Serponix is an arcade game in focus to multiplayer based on the classic game Snake.
 *  Copyright (C) 2010 - 2011  Daniel Vala
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License,
 *  or  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.

 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  If you have any question do not hesitate to contact author
 *  on e-mail address: danielvala42@gmail.com
 */
package com.serponix.game;

import com.serponix.game.food.Cake;
import com.serponix.game.food.Cherry;
import com.serponix.game.objektyNaPlose.Clanek;
import com.serponix.game.projectiles.Laser;
import com.serponix.game.projectiles.Rocket;
import com.serponix.game.score.Score;
import com.serponix.gui.WindowInterface;
import com.serponix.net.Informace;
import java.awt.AlphaComposite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.swing.JLabel;

/**
 * Model pro hru klient obsahuje políčka, které každý krok vykresluje.
 *
 * @author Daniel Vala
 */
public class ModelClient extends GameModel {

	private List<Policko> policka;
	private ReentrantReadWriteLock zamek;

	public ModelClient(WindowInterface okno, GameParameters parametryHry, GamingArea herniPanel, JLabel[] skoreStitky, MessagePanel panelZprav) {
		super(okno, parametryHry, herniPanel, skoreStitky, panelZprav, parametryHry.getSizeOfGamingArea());
		parametryHry.getClient().setModel(this);
		net = parametryHry.getClient();
		policka = new ArrayList<Policko>();
		zamek = new ReentrantReadWriteLock();
	}

	/**
	 * Přidá do pole políčko, které klient v příštím kroku hry vykreslí.
	 *
	 * @param policko Políčko k vykreslení.
	 */
	public void pridejPolicko(Policko policko) {
		zamek.writeLock().lock();
		try {
			policka.add(policko);
		} finally {
			zamek.writeLock().unlock();
		}
	}

	public void smazVsechnyPolicka() {
		zamek.writeLock().lock();
		try {
			policka.clear();
		} finally {
			zamek.writeLock().unlock();
		}
	}

	public void posliPrikazServeru(String prikaz) {
		net.poslatData(prikaz);
	}

	public void posliPrikazServeru(int prikaz) {
		net.poslatData(prikaz + "");
	}

	public void posliNastaveniHry() {
	}

	public void posliStav() {
	}

	@Override
	public void resetHada(Snake had) {
	}

	@Override
	public void newRound() {
	}

	@Override
	public void jidloSezrano(Snake had) {
	}

	@Override
	public void bonusSezran(Snake had) {
	}

	@Override
	public void addScore(Score skore, int body) {
	}

	@Override
	public void krok() {
		setChanged();
		notifyObservers();
	}

	@Override
	public void paint(Graphics g) {
		Graphics2D g2d = (Graphics2D) g;
		zamek.readLock().lock();
		try {
			for (Policko policko : policka) {

				// pokud políčko obsahuje barvu
				if (policko.getBarva() != null) {
					g2d.setPaint(policko.getBarva());
				}
				if (policko.getTyp() == Informace.HAD) {
					int informace = policko.getInformace();
					if (policko.getNeviditelnost()) {
						Clanek.NastavNeviditelneKresleni(g2d);
					}
					switch (informace) {
						case Informace.CLANEK:
							Clanek.paint(g2d, policko.getX(), policko.getY(), getVelikostPolicka());
							break;
						case Informace.ODOLNOST:
							Clanek.paintOdolny(g2d, policko.getX(), policko.getY(), getVelikostPolicka());
							break;
						case Informace.DUCH:
							Clanek.paintDuch(g2d, policko.getX(), policko.getY(), getVelikostPolicka());
							break;
						case Informace.HLAVA:
							Clanek.paintHlava(g2d, policko.getX(), policko.getY(), getVelikostPolicka(), policko.getSmer());
							break;
						case Informace.HLAVA_TANKU:
							Clanek.paintHlavaTank(g2d, policko.getX(), policko.getY(), getVelikostPolicka(), policko.getSmer());
							break;
					}
					// nastavení průhlednosti zpět na normální hodnotu
					g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1));
				} else if (policko.getTyp() == Informace.LASER) {
					Laser.paint(g2d, policko.getX(), policko.getY(), policko.getSmer());
				} else if (policko.getTyp() == Informace.RAKETA) {
					Rocket.paint(g2d, policko.getX(), policko.getY(), policko.getSmer());
				} else if (policko.getTyp() == Informace.JIDLO) {
					Cake.paint((Graphics2D) g, policko.getX(), policko.getY());
				} else if (policko.getTyp() == Informace.BONUS) {
					Cherry.paint((Graphics2D) g, policko.getX(), policko.getY());
				} else if (policko.getTyp() == Informace.SMAZ_ZED) {
					getMapa().smazZed(policko.getX(), policko.getY());
				}
			}
		} finally {
			zamek.readLock().unlock();
		}
		smazVsechnyPolicka();
	}

	@Override
	void paintZdi(Graphics g) {
		getMapa().kresliMapu(g);
	}
}
